const cheerio = require('cheerio')
const rewire = require('rewire')
const {readFile, makeDir, saveFile, existDir} = rewire('../common/file.cjs')
const {httpGet, httpPost, urlEncode, generateUUID, currentMs, uuid, arraySub, splitArray, extractNum} = rewire('../common/utils.cjs')
const {filterAsync, makeNotFn, createParallelRunner, errorRetry, parallelMap} = rewire('../common/combinator.cjs')
const { PrismaClient, Prisma } = require('@prisma/client')
const { deleteRedundantSql } = require('../common/dbutils.cjs')
const { parseSpec } = require('../common/regex.cjs')
const R = require('ramda')

const prisma = new PrismaClient()

async function main() {
    const topCategorys = await getTopCategorys()
    const len = topCategorys.length
    for (let i = 0; i < len; i++) {
        const topName = topCategorys[i]
        console.log("开始：" + topName)
        const subNameList = await getSubCategory(topName)
        for (let subName of subNameList) {
            console.log("--开始：" + subName)
            await doCategory(subName)
            await sleep(1000)
        }
    }
}

async function main2() {
    const topCategorys = await getTopCategorys()
    const len = topCategorys.length
    for (let i = 0; i < len; i++) {
        const topName = topCategorys[i]
        console.log("检查开始：" + topName)
        const subNameList = await getSubCategory(topName)
        for (let subName of subNameList) {
            const total = await getTwoDataTotal(subName)
            if (total > 10000) {
                console.log("--开始爬取：" + subName)
                await fixCategory(subName)
            }
            await sleep(100)
        }
    }
    console.log("完成了")
}

async function main3() {
    const keywords = JSON.parse(readFile('e:/xie.txt'))
    await parallelMap(
        2,
        async function(keyword) {
            let data = await searchKeyWord(keyword)
            data = await filterUnFetch(data)
            await parallelMap(1, handleDetail, data)
        },
        keywords
    )
    console.log('全部完成')
}

async function mainTask(filePath) {
  const keywords = JSON.parse(readFile(filePath))
  const filterIds = await filterUnFetch(keywords)
  await parallelMap(
    2,
    async function(keyword) {
      const kk = keyword.endsWith("号") ? keyword.slice(0, -1) : keyword
      let data = await searchKeyWord2(kk)
      let ids = data.map(item => item['proId'])
      data = await filterUnFetch2(ids)
      await parallelMap(1, handleDetail2, data)
    },
    filterIds
  )
  console.log('全部完成')
}

async function main4() {
  mainTask('e:/aaa.data')
}

async function main5() {
  mainTask('/Users/huangyesheng/Documents/project/media/20220118.data')
}

async function filterUnFetch(ids) {
    if (R.length(ids) == 0) {
        return []
    }
    const dbdata = await prisma.$queryRaw`SELECT proId FROM jixie WHERE proId IN (${Prisma.join(ids)})`
    const readIds = dbdata.map(item => item['proId'])
    return arraySub(ids, readIds)
}

async function filterUnFetch2(data) {
    const ids = data.map(item => item['proId'])
    if (R.length(ids) == 0) {
        return []
    }
    const dbdata = await prisma.$queryRaw`SELECT proId FROM jixie WHERE proId IN (${Prisma.join(ids)})`
    const readIds = dbdata.map(item => item['proId'])
    return arraySub(ids, readIds)
}


async function checkUnFetch() {
    const ids = []
    const dbdata = await prisma.$queryRaw`SELECT * FROM jixie WHERE registrationNum IN (${Prisma.join(ids)})`
    const readIds = dbdata.map(item => item['proId'])
    return arraySub(ids, readIds)
}


async function handleDetail(id) {
    const url = `https://api.zhixie.info/api/smallProgram/product/productDetail?uid=${id}&api_key=zhixie`
    const resp = await httpGet(url)
    const data = resp.data
    const info = data['data']
    if (data['status'] == 200) {
        const rs = {
            proId: id,
            esId: '',
            productName: info['productNameCh'],
            enterpriseName: info['makerNameCh'],
            registrarAddress: info['makerAddrCh'],
            productionAddress: info['productionSiteCh'],
            approvalDepart: info['approvalDept'],
            registrationNum: info['registerCode'],
            approvalDate: info['approvalDate'],
            validDate: info['expiryDate'],
            category: info['managementCategory'] + '',
            modelSpeci: info['productMode'],
            modelSpeci_split: '0',
            isSplit: 0,
            applyRange: info['purpose'],
            prodMatter: '',
            sampleName: info['productNameEn'],
            intendedUse: info['productScope'],
            structure: info['mainComponent'],
            prodDesc: info['productStruct'],
            largeClassName: info['zhixieCatgoryName'],
            oneProdCategory: info['categoryList'][0]['firstName'],
            twoProdCategory: info['categoryList'][0]['secondName'],
            status: info['isValid'] ? '有效' : '注销',
            productType: '未知',
            prodMature: info['categoryList'][0]['expectedUse'],
            province: info['province'],
            year: '',
            registType: '',
            proper: '',
            created_at: currentMs(),
            registNum: info['registerCode'],
            entId: '',
            city: '',
            updatedAt: 0,
            isDetail: 1,
            json: JSON.stringify(info)
        }
        await prisma.jixie.create({
            data: rs
        })
    }
}

async function handleDetail2(id) {
    const url = `https://xqc.mdsight.cn/api/machinery/product/getProductDetails?id=${id}&productType=%E5%9B%BD%E4%BA%A7&productName=`
    const resp = await httpGet(url)
    const data = resp.data

    if (data && data['proId']) {
  const {collectionVo, pid, monitorStatus, ...info} = data
  info['created_at'] = currentMs()
  await prisma.jixie.create({
            data: info
  })
    }
}

async function searchKeyWord(keyword) {
    let result = []
    async function loop(page) {
        const url = `https://api.zhixie.info/api/smallProgram/product/productSearchKey?keyword=${urlEncode(keyword)}&page=${page}&productAscription=&valid=&managementCategory=&api_key=zhixie`
        const resp = await httpGet(url)
        const data = resp.data
        if (data['status'] == 200) {
            const content = data['data']['content']
            if (page == 1 && R.length(content) == 0) {
                console.info('找不到械字号：' + keyword)
            }
            else {
                const total = data['data']['totalElements']
                result = R.concat(result, content)
                if (total > R.length(result)) {
                    await loop(page + 1)
                }
            }
        }
        else {
            console.error(data)
            throw new Error('访问出问题了')
        }
    }

    await loop(1)
    return result
}

async function searchKeyWord2(keyword) {
    let result = []
    async function loop(page) {
        const url = `https://xqc.mdsight.cn/api/search/product/getProductList?largeClassName=&oneProdName=&twoProdName=&keyword=${urlEncode(keyword)}&province=&city=&proper=&category=&productType=&status=&startYear=&endYear=&pageIndex=1&pageSize=10`
        const resp = await httpGet(url)
        const data = resp.data
        if (data) {
            const content = data['records']
            if (page == 1 && R.length(content) == 0) {
                console.info('找不到械字号：' + keyword)
            }
            else {
                //console.info('正在爬械字号：' + keyword)
                const total = data['total']
                result = R.concat(result, content)
                if (total > R.length(result)) {
                    await loop(page + 1)
                }
            }
        }
        else {
            console.error(data)
            throw new Error('访问出问题了')
        }
    }

    await loop(1)
    return result
}

function isString(obj) {
    return obj && typeof(obj) == "string"
}

async function splitRecordTask() {
    const allData = await getAllSpecJixie()
    for (let item of allData) {
        console.log("处理：" + item.proId)
        let json = JSON.parse(item.modelSpeci_split)
        if (isString(json)) {
            json = [json]
        }
        const newItems = uniqueItem(json).map(spec => {
            return {
                proId: item.proId,
                productName: item.productName,
                modelSpeci: (isString(spec) ? spec : JSON.stringify(spec)),
                registrationNum: item.registrationNum
            }
        })
        await saveJixieSplitList(newItems)
    }
    console.log("跑完了")
}

async function ekPicTask() {
    const allEkData = await getAllEkPicData()
    await parallelMap(10, handlerEkPic, allEkData)
    console.log('跑完了')
}

const axios = require('axios')
const fs = require('fs')
async function handlerEkPic(info) {
    async function ekPicSave(url) {
        console.log('正在获取图片：' + url)
        if (!/http.*?\.(jpg|png|gif)/.test(url)) {
            return
        }
        const urlPies = url.split('/')
        const path = `${imgPath}/${urlPies[urlPies.length - 2]}`
        if (!existDir(path)) {
            makeDir(path)
        }
        try {
            const resp = await axios({
    url,
    responseType: 'arraybuffer'
            })
            fs.writeFileSync(`${path}/${urlPies[urlPies.length - 1]}`, resp.data, 'binary')
        } catch (e) {
            console.error('图片获取失败' + url)
        }

    }
    const urls = JSON.parse(info.picList)
    await parallelMap(10, ekPicSave, urls)
}

async function getAllEkPicData() {
    const data = await prisma.$queryRaw`SELECT * FROM jixie_ek WHERE picList <> '[]'`
    return data
}

async function grapElinkmedicalTask() {
    const allCategory = await getAllEkCategory()

    for (let categoryId of allCategory) {
        let productIds = await getEkProductIdList(categoryId)
        productIds = await filterEkUnRead(productIds)
        await parallelMap(10, handlerEkDetail, productIds)
    }
    console.log('已完成')
}

async function filterEkUnRead(ids) {
    if (!ids || ids.length <= 0) {
        return []
    }
    const data = await prisma.$queryRaw`SELECT * FROM jixie_ek WHERE productId IN (${Prisma.join(ids)})`
    const readIds = data.map(item => item['productId'])
    return arraySub(ids, readIds)
}



async function getEkProductIdList(id) {
    async function fetch() {
        const resp = await httpPost(`https://eduapi.jxelink.com/egoodsDetail/findEgoodsList`, {"pageIndex":1,"pageSize":15000,"isSortByPrice":0,"name":"","spot":false,"refund":false,"eclassInfoId":id,"cancelToken":{"promise":{}}})
        if (resp.data['errno'] !== 0) {
            throw new Error('获取EK列表信息出错')
        }
        if (resp.data['data']['total'] > 15000) {
            throw new Error('EK列表格式超出' + id)
        }
        return resp.data['data']['data']
    }
    const data = await fetch()
    const rs = data.map(item => { return item.id })
    return rs
}

//getEkProductIdList(376)

async function getAllEkCategory() {
    const resp = await httpGet(`https://eduapi.jxelink.com/classify/getClassInfopc`)
    const data = resp.data['data'].map(item => { return item.map(info => { return info['id'] }) })
    const rs = [].concat(...data)
    return rs
}

//getAllEkCategory()

async function handlerEkDetail(productId) {
    console.log('正在处理：' + productId)
    const html = await getEkDetail(productId)
    const detail = parseEkDetail(html)
    const picList = parseEkPic(html)
    detail['id'] = uuid()
    detail['productId'] = productId
    detail['picList'] = JSON.stringify(picList)
    await saveEkDetail(detail)
}

async function saveEkDetail(detail) {
    await prisma.jixie_ek.create({
        data: detail
    })
}

async function getEkDetail(productId) {
    const rs = await httpGet(`https://www.elinkmedical.com/goodsDetail?id=${productId}`)
    const data = rs.data
    if (!data.includes('生产厂家：</span> <p class="text" data-v-1ae7c496>')) {
        throw new Error('获取产品信息出错：' + productId)
    }
    return data
}
//getEkDetail(11689)

function parseEkDetail(html) {
    function parse(reg) {
        let rs = reg.exec(html)
        if (!rs || rs.length < 2) {
            throw new Error('解析内容有问题:' + reg)
        }
        return rs[1].trim()
    }
    let regObj = {
        factory: /生产厂家：<\/span> <p class="text" data-v-[a-z0-9]{5,10}>(.*?)<\/p><\/li>/,
        license: /生产许可证或备案凭证编号：<\/span> <p class="text" data-v-[a-z0-9]{5,10}>\s+(.*?)\s+<\/p><\/li>/,
        registrationNum: /注册证号：<\/span> <p class="text" data-v-[a-z0-9]{5,10}>\s+(.*?)\s+<\/p><\/li>/,
    }

    let rs = {}
    for (let k in regObj) {
        rs[k] = parse(regObj[k])
    }
    return rs
}

//parseEkDetail(readFile('../tmp/ek2.html'))

function parseEkPic(html) {
    const chars = 'a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z'.split(', ')
    const regParams = /,img:([a-z]{1,2}),/
    const params = regParams.exec(html)
    const paramsName = params[1]
    const paramsIndex = chars.findIndex(v => v === paramsName)

    const reg = /cdnURL:[a-zA-Z]\}\}\}\}\((.*?)\)\);<\/script>/g
    let rs = reg.exec(html)
    if (!rs || rs.length < 2) {
        return []
    }
    rs = '[' + rs[1] + ']'
    rs = rs.replaceAll(/,\.([0-9]{1,5})/g, ',0.$1')
    const data = JSON.parse(rs)
    const urls = data[paramsIndex].split(',')
    return urls
}



function uniqueItem(arr) {
    return Array.from(new Set(arr))
}

function makeCommonSpecHandler(split, num) {
    return async function() {
        const data = await getNeedModel()
        const len = data.length
        console.log("需要处理的总数" + len)
        for (let i = 0; i < len; i++) {
            let item = data[i]
            const specList = split(item.modelSpeci)
            if (specList) {
                console.log(item.proId)
                item.modelSpeci_split = JSON.stringify(specList)
                item.isSplit = num
                await saveItem(item)
            }
        }
        console.log("完成了")
    }
}


const sleep = (time) => {
    return new Promise(resolve => setTimeout(resolve, time))
}

async function getTopCategorys2() {
    return ['医用康复器械', '中医器械', '医用软件']
}

async function getSubCategory(topName) {
    const name = urlEncode(topName)
    const url = `https://xqc.joinchain.cn/api/database/product/getProdCategoryList?largeClassName=${name}`
    const resp = await httpGet(url)
    let data = resp.data
        .map(item => { return item.list.map(info => { return [info.name, info.type] }) }).flat()
    //data = await filterAsync(data, makeNotFn(checkFechedCategory))
    const rs = data.map(item => { return item[0].trim() }).filter(item => { return item && item != '' && item != '-'})
    console.log(rs)
    return rs
}

async function checkFechedCategory(info) {
    const name = info[1]
    return await prisma.jixie.findFirst({
        where: { twoProdCategory: name }
    })
}



// getSubCategory('有源手术器械')

async function getTopCategorys() {
    const url = `https://xqc.joinchain.cn/api/database/product/getLargeClassList`
    const resp = await httpGet(url)
    const data = resp.data.map(item => { return item['type'] })
    return data
}

async function doCategory(categoryName) {
    async function loop(page) {
        const data = await getTwoData(categoryName, page, 10000)

        if (data.code == 500) {
            return
        }

        const total = data['total']
        const rs = data['records']

        if (rs.length > 0) {
            await saveList(rs)
        }

        if (total > 10000) {
            console.log("存在不完整的分类：" + categoryName)
        }
    }
    await loop(1)
}

//fixCategory('物理降温设备')

async function fixCategory(categoryName) {
    async function loop(data) {
        if (data.code == 500) {
            return
        }

        const total = data['total']
        const rs = data['records']

        if (rs.length > 0) {
            await saveList(rs)
        }

        if (total > 10000) {
            console.log("存在不完整的分类：" + categoryName)
        }
    }

    const data1 = await getTwoDataByYear(categoryName, 1, 10000, 2018)
    await loop(data1)
    const data2 = await getTwoDataByYear(categoryName, 1, 10000, '', 2018)
    await loop(data2)
}



async function getTopData(subCategoryName, page, size) {
    const name = urlEncode(subCategoryName)
    const url = `https://xqc.joinchain.cn/api/search/product/getProductList?largeClassName=${name}&oneProdName=&twoProdName=&keyword=&province=&city=&proper=&category=&productType=&status=&startYear=&endYear=&pageIndex=${page}&pageSize=${size}`
    const resp = await httpGet(url)
    const data = resp.data

    await saveQueryResult(subCategoryName, url, JSON.stringify(data))
    return data
}

async function getOneData(subCategoryName, page, size) {
    const name = urlEncode(subCategoryName)
    const url = `https://xqc.joinchain.cn/api/search/product/getProductList?largeClassName=&oneProdName=${name}&twoProdName=&keyword=&province=&city=&proper=&category=&productType=&status=&startYear=&endYear=&pageIndex=${page}&pageSize=${size}`
    const resp = await httpGet(url)
    const data = resp.data

    await saveQueryResult(subCategoryName, url, JSON.stringify(data))
    return data
}

async function getTwoData(subCategoryName, page, size) {
    return await getTwoDataByYear(subCategoryName, page, size)
}

async function getTwoDataByYear(subCategoryName, page, size, start = '', end = '') {
    const name = urlEncode(subCategoryName)
    const url = `https://xqc.joinchain.cn/api/search/product/getProductList?largeClassName=&oneProdName=&twoProdName=${name}&keyword=&province=&city=&proper=&category=&productType=&status=&startYear=${start}&endYear=${end}&pageIndex=${page}&pageSize=${size}`
    const resp = await httpGet(url)
    const data = resp.data

    await saveQueryResult(subCategoryName, url, JSON.stringify(data))
    return data
}

async function getTwoDataTotal(subCategoryName) {
    const name = urlEncode(subCategoryName)
    const url = `https://xqc.joinchain.cn/api/search/product/getProductList?largeClassName=&oneProdName=&twoProdName=${name}&keyword=&province=&city=&proper=&category=&productType=&status=&startYear=&endYear=&pageIndex=1&pageSize=10`
    const resp = await httpGet(url)
    const data = resp.data

    const total = data['total']

    return total
}

async function saveQueryResult(name, url, xml) {
    const item = {
        id: generateUUID(),
        category_name: name,
        url: url,
        resp: xml,
        created_at: currentMs()
    }
    await prisma.jixie_list.create({
        data: item
    })
}

async function saveList(data) {
    const rsList = splitArray(data, 100)
    for (let rsItem of rsList) {
        await Promise.all(
            rsItem.map((info) => {
                return prisma.jixie.upsert({
                    where: { proId: info.proId },
                    update: info,
                    create: info,
                })
            })
        )
    }
}


// 查询
async function getNeedModel() {
    const data = await prisma.jixie.findMany({
        where: { modelSpeci_split: '0', modelSpeci: {not: ''}, modelSpeci: {not: {contains: '见'}} },
        select: {proId: true, modelSpeci_split: true, modelSpeci: true, isSplit: true},
        //take: 5000, 
    })
    return data
}

async function saveItem(info) {
    await prisma.jixie.upsert({
        where: { proId: info.proId },
        update: info,
        create: info,
    })
}


async function saveJixieSplitList(data) {
    for (let info of data) {
        const isExits = await prisma.jixie_split.findFirst({
            where: { proId: info.proId, modelSpeci: info.modelSpeci }
        })
        if (isExits) {
            return await prisma.jixie_split.update({
                where: { id: isExits.id },
                data: info
            })
        }
        else {
            return await prisma.jixie_split.create({
                data: {...info, id: uuid()}
            })
        }
    }
}

async function getAllSpecJixie() {
    const data = await prisma.$queryRaw`SELECT * FROM jixie WHERE proId not in (select proId from jixie_split group by proId) and modelSpeci_split<>'0' and modelSpeci<>''`
    // const splitList = await prisma.jixie_split.groupBy({
    //  by: ['proId']
    // })

    // const proIds = splitList.map(item => { return item.proId })
    // const data = await prisma.jixie.findMany({
    //  where: { proId: {not: {in: proIds}}, modelSpeci_split: {not: "0"}, modelSpeci: {not: ''} },
    // })
    console.log('总共：' + data.length)
    return data
}

let errorList = []

async function autoFillItemDetail(proId) {
    try {
        const url = `https://xqc.joinchain.cn/api/machinery/product/getProductDetails?id=${proId}&productType=&productName=`;
        console.log("爬取中：" + proId)
        const resp = await httpGet(url)
        const data = resp.data
        if (data.code && data.code == 500) {
            console.log("爬取失败" + proId)
        }
        data.updatedAt = currentMs()
        data.isDetail = 1
        delete data.collectionVo
        delete data.pid
        delete data.monitorStatus
        await saveItem(data)
        return data
    } catch(e) {
        errorList.push(proId)
        console.log(e.message)
        return null
    }
}


async function detailTask() {
    const proIdList = await getAllProIdList()
    const f = createParallelRunner((data) => {
        const len = data.length
        const parallelNum = 8
        let rs = Array.from({length: parallelNum}, (v, i)=> [])
        for (let i = 0; i < len; i++) {
            rs[(i % parallelNum)].push(data[i])
        }
        return rs
    }, proIdList, autoFillItemDetail)
    await f()
}

async function getAllProIdList() {
    const data = await prisma.jixie.findMany({
        where: { isDetail: 0 },
        //take: 100000, 
        select: {proId: true}
    })
    const rs = data.map(item => { return item.proId })
    return rs
}





// parallelMap(10, async function(i) {
//     console.log(i)
//     return `done: ${i}`
// }, Array.from({length:100}, (v,k) => k))


function xmlToData(xmlStr) {
    function loop(root) {
        const children = root.children()
        let rs = {}
        if (children && children.length > 0) {
            const cdata = children.map(function(i, elem) {
                return loop($(this))
            }).get()
            if (cdata.length > 2 && Object.keys(cdata[0])[0] == Object.keys(cdata[1])[0]) {
                rs[root.get(0).tagName] = cdata
            }
            else {
                rs[root.get(0).tagName] = Object.assign(...cdata)
            }
        }
        else {
            rs[root.get(0).tagName] = root.text()
        }
        return rs
    }

    const $ = cheerio.load(xmlStr)
    const root = $('body').children().first()
    return loop(root)
}

function singleString(s) {
    const sourceStr = washStr(s)
    const len = sourceStr.length
    if (len > 15) {
        return false
    }
    const reg = /^([a-z0-9A-Z_ _-])+$/
    if (reg.test(sourceStr)) {
        return sourceStr
    }
    return false
}

function splitString(sourceStr) {
    const fixStr = washStr(sourceStr)    // 清洗字符串，比如删掉末尾的。
    const mayList = splitByFixedChar(fixStr)  // 使用固定分隔符进行分割
          .filter(item => { return item.length > 1 })  // 过滤
          .filter(isSimilar)

    if (mayList.length == 0) {
        return false
    }

    mayList.sort(function(a, b) {
        return b.length - a.length
    })

    return mayList[0]
}


function washStr(s) {
    return s.replace("。", "")
}

function splitByFixedChar(s) {
    const fixedChar = ['.', '、', /;|；/, /,|，/]
    const rs = fixedChar.map(c => { return s.split(c).map(s => { return s.trim() }) })
    return rs
}

function isSimilar(arr) {
    function allPrefixSame(arr, i) {
        const c = arr[0][i]
        const clen = arr[0].length
        for (let j = 1; j < arr.length; j++) {
            if ((arr[j][i] != c) || (Math.abs(clen - arr[j].length) > 4) || /:|：/.test(arr[j])) {
                return false
            }
        }
        return true
    }
    function allSuffixSame(arr, i) {
        const flen = arr[0].length
        const c = arr[0][flen - i - 1]
        for (let j = 1; j < arr.length; j++) {
            const len = arr[j].length
            if ((arr[j][len - i - 1] != c) || (Math.abs(flen - len) > 4) || /:|：/.test(arr[j])) {
                return false
            }
        }
        return true
    }

    function fSimilar(f, arr) {
        function loop(i) {
            if (arr[0].length <= i) {
                return i
            }
            else if (f(arr, i)) {
                return loop(i + 1)
            }
            else {
                return i
            }
        }
        return loop(0)
    }

    const charNotSimilar = arr.filter(item => { return !(/^([a-z0-9A-Z_ _-_\/])+$/.test(item))}).length
    if (charNotSimilar) {
        return fSimilar(allPrefixSame, arr) + fSimilar(allSuffixSame, arr)
    }
    else {
        return true
    }

}



function nestEachFn(fn, ...args) {
    if (R.length(args) % 2 != 0) {
        throw new Error('参数有问题')
    }
    if (R.length(args) == 0) {
        return fn
    }
    const eachFn = args[0]
    return async (...params) => {
        const data = await fn(...params)
        const f2 = nestEachFn(...(R.drop(1, args)))
        return await eachFn(f2, data)
    }
}

const commonMap = R.partial(parallelMap, [1])

async function fetchCgpoCategory() {
    const resp = await httpGet('http://www.cgpo.cn/Cat/index/id/511.html')
    const html = resp.data
    const $ = cheerio.load(html)
    const categoryList = $('.category_cate > dl > dt > a').map(function(i, el) {
        return {
            url: $(this).attr('href'),
            text: $(this).text()
        }
    }).toArray()
    return categoryList
}

async function fetchCgpoPage(categoryInfo) {
    console.log('正在爬取列表：' + categoryInfo.text)
    const id = extractNum(categoryInfo.url)

    async function fetchPage(page = 1) {
        console.log(`第${page}页`)
        const url = `http://www.cgpo.cn/Cat/index/id/index.html?id=${id}&page=${page}`
        const resp = await httpGet(url)
        const html = resp.data
        const $ = cheerio.load(html)
        const categoryList = $('ul.category_pro_list > li > div.category_pro_pic > a').map(function(i, el) {
            return $(this).attr('href')
        }).toArray()

        const pageHtml = $('div.category_result div.result').html()
        if (pageHtml && R.contains('尾页', pageHtml)) {
            const leftRs = await fetchPage(page + 1)
            return R.concat(categoryList, leftRs)
        }
        return categoryList
    }
    return await fetchPage()
}

async function fetchCgpoItem(sourceUrl) {
    const url = `http://www.cgpo.cn${sourceUrl}`
    console.log(url)
    const resp = await errorRetry(httpGet, 3)(url)
    const html = resp.data
    const $ = cheerio.load(html)
    const imgList = $('div.ware_box > ul > li').map(function(i, el) {
        return $(this).attr('bigimg')
    }).toArray()
    const wdElems = $('ul.details_info1 > li.wd > span').map(function(i, el) { return $(this).text() }).toArray()
    const registrationNum = wdElems[1]
    const license = wdElems[2]
    const factory = wdElems[3]
    const detail = $('.g_goods_dp_desc').text() + '\n' + $('.prcontent').text()
    await saveCgpoItem({
        registrationNum,
        factory,
        license,
        picList: JSON.stringify(imgList),
        productId: extractNum(url),
        detail
    })
}

async function saveCgpoItem(info) {
    return prisma.jixie_cgpo.upsert({
        where: { productId: info.productId },
        update: info,
        create: info,
    })
}


// (async () => {
//     const rs = await fetchCgpoItem('/Product/detail/id/1293.html')
//     console.log(rs)
// })()
// const ffff = nestEachFn(fetchCgpoCategory, commonMap, fetchCgpoPage, R.partial(parallelMap, [3]), fetchCgpoItem)
// ffff()




let splitSpecHandler1 = makeCommonSpecHandler(singleString, 1)

let splitSpecHandler2 = makeCommonSpecHandler(splitString, 2)

let splitSpecHandler3 = makeCommonSpecHandler(parseSpec, 3)

// 型号规格字段拆分
async function specHandler() {
    await splitSpecHandler1()
    await splitSpecHandler2()
    await splitSpecHandler3()
}

const imgPath = 'd:/media'

async function ekTask() {
    const f = errorRetry(grapElinkmedicalTask, 10)
    await f()
    await ekPicTask()
}

//splitRecordTask()
//

//ekPicTask()

//console.log(deleteRedundantSql('jixie_ek', 'productId'))
//parseEkPic(readFile('../tmp/ek2.html'))

main5()

// splitString('型号1：LR1s；型号2：LR2s；型号3：LR3s；型号4：LR4s；型号5：LR1；型号6：LR2')
// splitString('JSL2009-5+3；JSL2009-4+3;JSL2009-3+3;JSL2009-3')
// splitString('试剂1：4×20ml 试剂 2：2×10ml； 试剂1：4×30ml 试剂2：2×15ml；试剂1：4×50ml 试剂2：1×50ml；试剂1：4×60ml 试剂2：1×60ml； 试剂1：2×60ml 试剂2：2×15ml；试剂1：4×100ml 试剂2：1×100ml； 试剂1：2×40ml 试剂2：2×10ml； 试剂1：4×20ml 试剂2：1×20ml； 试剂1：4×20ml 试剂2：4×5ml； 试剂1：4×70ml 试剂2：1×70ml')
// splitString('YDB-T（标准无包边）；规格：30cm*14cm；30cm*20cm；35cm*25cm；40cm*30cm；45cm*35cm；23cm*18cm；20cm*15cm；18cm*13cm；YDZ-T（枕型塑形无包边）')
// splitString('型号：药铜200；规格：大号、中号、小号')
// splitString('型号：Normal Smooth（普通平面型）、Ribbed（螺纹型）、Dotted（颗粒型）；规格：52±2mm')
// splitString('S-1.3型、C-6型、C-7A型、C-7B型、A-17型、H型')
// splitString('光面型（smooth）、非光面型(unusually smooth)')
// splitString('Sagami Original,尺寸：长170mm、直径36mm；Sagami Original大号，尺寸：长190mm、直径37mm')
// splitString('110-001, 110-002, 110-003, 110-004, 114-009, 117-016, 120-009, 117-205, 120-008')
//console.log(splitString('UltraPulse Encore'))
// 'JSL2009-5+3；JSL2009-4+3;JSL2009-3+3;JSL2009-3'.split(/;|；/)
